package com.example.flutter_cjadsdk_plugin

import android.app.Activity
import android.app.Application
import android.content.Context
import android.content.Intent
import android.content.res.Resources
import android.util.Log
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.annotation.NonNull
import cj.mobile.CJInterstitial
import cj.mobile.CJMobileAd
import cj.mobile.CJRewardVideo
import cj.mobile.CJSplash
import cj.mobile.listener.CJInitListener
import cj.mobile.listener.CJInterstitialListener
import cj.mobile.listener.CJRewardListener
import cj.mobile.listener.CJSplashListener
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import org.json.JSONObject
import java.lang.reflect.InvocationTargetException

// 激励视频预加载方法
const val preReward = "preReward"
// sdk初始化
const val setupFuncName = "cjSdkSetup"
const val splashFuncName = "cjLoadAndShowSplashMethod"
const val rewardVideoFuncName = "cjLoadAndShowRewardVideoMethod"
const val fullscreenVideoFuncName = "cjLoadAndShowFullscreenVideoMethod"
const val interstitialFuncName = "cjLoadAndShowInterstitialAdMethod"
const val shortVideoFuncName = "getShortVideoAdMethod"

const val setupSuccess = "setupSuccess"
const val setupFailured = "setupFailured"
const val splashAdLoadSuccess = "splashAdLoadSuccess"
const val splashAdLoadFailed = "splashAdLoadFailed"
const val splashAdClickEvent = "splashAdClickEvent"
const val splashAdCloseEvent = "splashAdCloseEvent"
const val rewardVideoAdBeRewarded = "rewardVideoAdBeRewarded"
const val rewardVideoAdLoadSuccess = "rewardVideoAdLoadSuccess"
const val rewardVideoAdLoadFailed = "rewardVideoAdLoadFailed"
const val rewardVideoAdClickEvent = "rewardVideoAdClickEvent"
const val rewardVideoAdCloseEvent = "rewardVideoAdCloseEvent"

/** FlutterCjadsdkPlugin */
class FlutterCjadsdkPlugin: FlutterPlugin, MethodCallHandler {

  /// The MethodChannel that will the communication between Flutter and native Android
  ///
  /// This local reference serves to register the plugin with the Flutter Engine and unregister it
  /// when the Flutter Engine is detached from the Activity
  private lateinit var splashContentView: FrameLayout
  private lateinit var channel : MethodChannel
  private lateinit var splashAd: CJSplash
  private lateinit var rewardAd: CJRewardVideo
  private lateinit var interstitial: CJInterstitial

  private var width: Int = 0
  private var height: Int = 0
  private var isPro: Boolean = false


  override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
    channel = MethodChannel(flutterPluginBinding.binaryMessenger, "flutter_cjadsdk_plugin")
    channel.setMethodCallHandler(this)
  }

  override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
    var advertId = call.argument<String>("advertId")
    var configId = call.argument<String>("configId")
    var userId = call.argument<String>("userId")
    when(call.method) {
      in preReward -> {
        var activity = getCurrentActivity()
        //预加载激励视频
        CJRewardVideo.getInstance()
          .setMainActivity(activity)
          .loadAd(advertId)
      }
      in setupFuncName -> {
        CJMobileAd.emulatorShowAd(false)
        val application: Application? = AppGlobalUtils().application;
        CJMobileAd.init(application, configId, object : CJInitListener {
          override fun initFailed(errorMsg: String) {
            channel.invokeMethod(setupFailured, errorMsg)
          }

          override fun initSuccess() {
            channel.invokeMethod(setupSuccess, "成功")
          }
        })
      }
      in splashFuncName -> {
        var widthTemp = Resources.getSystem().displayMetrics.widthPixels
        var heightTemp = Resources.getSystem().displayMetrics.heightPixels
        splashAd = CJSplash()
        var activity = getCurrentActivity()
        if (activity != null) {
          splashContentView = FrameLayout(activity)
          (activity.window.decorView as? ViewGroup)!!.addView(splashContentView)
          width = dip2px(activity, widthTemp.toFloat())
          height = dip2px(activity, heightTemp.toFloat())
        }
        splashAd.loadAd(activity, advertId, width, height, object : CJSplashListener {
          override fun onShow() {
            channel.invokeMethod("onShow", null)
          }

          override fun onError(s: String, s1: String) {
            val map: MutableMap<String, Any> = HashMap()
            map["code"] = s
            map["message"] = s1
            channel.invokeMethod(splashAdLoadFailed, map)
          }

          override fun onLoad() {
            channel.invokeMethod(splashAdLoadSuccess, "成功")
            splashAd.showAd(splashContentView)
          }

          override fun onClick() {
            channel.invokeMethod(splashAdClickEvent, null)
          }

          override fun onClose() {
            channel.invokeMethod(splashAdCloseEvent, null)
            (activity?.window?.decorView as ViewGroup?)!!.removeView(splashContentView)
          }
        })
      }

      in rewardVideoFuncName -> {
        var activity = getCurrentActivity()
        //预加载激励视频
        CJRewardVideo.getInstance()
                .setMainActivity(activity)//传入上下文activity（需要activity是长期存活的，所以最好传入主页面的activity
        CJRewardVideo.getInstance().setUserId(userId)
        CJRewardVideo.getInstance().setListener(object : CJRewardListener {
          override fun onShow() {
            channel.invokeMethod("onShow", null)
          }

          override fun onError(s: String, s1: String) {
            val map: MutableMap<String, Any> = HashMap()
            map["code"] = s
            map["message"] = s1
            channel.invokeMethod(rewardVideoAdLoadFailed, map)
          }

          override fun onClick() {
            channel.invokeMethod(rewardVideoAdClickEvent, null)
          }

          override fun onClose() {
            channel.invokeMethod(rewardVideoAdCloseEvent, null)
          }

          override fun onVideoEnd() {
          }

          override fun onLoad() {
              if (!isPro){
                isPro=true
                channel.invokeMethod(rewardVideoAdLoadSuccess, null)
                CJRewardVideo.getInstance().showAd(activity)
              }
          }

          override fun onVideoStart() {

          }
          override fun onReward(s: String) {
            val jsonObject = JSONObject()
            jsonObject.put("requestId", s)
            channel.invokeMethod(rewardVideoAdBeRewarded, jsonObject.toString())
          }
        })
        if (CJRewardVideo.getInstance().isValid()) {
            isPro=true;
            CJRewardVideo.getInstance().showAd(activity)
        } else if (CJRewardVideo.getInstance().isLoading()) {
            isPro=false;
        } else {
            isPro=false;
            CJRewardVideo.getInstance().loadAd(advertId);
        }
      }
      in interstitialFuncName -> {
        // 加载插屏
        interstitial = CJInterstitial()
        var activity = getCurrentActivity()
        interstitial.loadAd(activity, advertId, object : CJInterstitialListener {
          override fun onShow() {
            channel.invokeMethod("onShow", null)
          }

          override fun onError(s: String, s1: String) {
            val map: MutableMap<String, Any> = java.util.HashMap()
            map["code"] = s
            map["message"] = s1
            channel.invokeMethod("onShow", map)
          }

          override fun onLoad() {
            channel.invokeMethod("onLoadInterstitial", null)
            interstitial.showAd(activity)
          }

          override fun onClick() {
            channel.invokeMethod("onClickInterstitial", null)
          }

          override fun onClose() {
            channel.invokeMethod("onCloseInterstitial", null)
          }
        })
      }
      in shortVideoFuncName-> {
        var context = AppGlobalUtils().application?.applicationContext
        var intent = Intent(context, ShortVideoActivity::class.java)
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        intent.putExtra("advertId", advertId)
        context?.startActivity(intent)
      }
      else -> {
        Log.e("100000","暂不支持")
        channel.invokeMethod("unkonw-support", "暂不支持")
//        result.notImplemented()
      }
    }
  }

  override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
    channel.setMethodCallHandler(null)
  }

  fun dip2px(context: Context, dpValue: Float): Int {
    val scale = context.resources.displayMetrics.density
    return (dpValue * scale + 0.5f).toInt()
  }

  fun getCurrentActivity(): Activity? {
    try {
      val activityThreadClass = Class.forName("android.app.ActivityThread")
      val activityThread = activityThreadClass.getMethod("currentActivityThread").invoke(
        null
      )
      val activitiesField = activityThreadClass.getDeclaredField("mActivities")
      activitiesField.isAccessible = true
      val activities = activitiesField[activityThread] as Map<*, *>
      for (activityRecord in activities.values) {
        val activityRecordClass: Class<*> = activityRecord?.javaClass!!
        val pausedField = activityRecordClass.getDeclaredField("paused")
        pausedField.isAccessible = true
        if (!pausedField.getBoolean(activityRecord)) {
          val activityField =
            activityRecordClass.getDeclaredField("activity")
          activityField.isAccessible = true
          return activityField[activityRecord] as Activity
        }
      }
    } catch (e: ClassNotFoundException) {
      e.printStackTrace()
    } catch (e: InvocationTargetException) {
      e.printStackTrace()
    } catch (e: NoSuchMethodException) {
      e.printStackTrace()
    } catch (e: NoSuchFieldException) {
      e.printStackTrace()
    } catch (e: IllegalAccessException) {
      e.printStackTrace()
    }
    return null
  }



  class AppGlobalUtils {
    private var myApp: Application? = null
    val application: Application?
    get() {
      if (myApp == null) {
        try {
          val currentApplication =
            Class.forName("android.app.ActivityThread").getDeclaredMethod("currentApplication")
            myApp = currentApplication.invoke(null) as Application
        } catch (e: Exception) {
          e.printStackTrace()
        }
      }
      return myApp
    }
  }
}
